package com.huawang.mdesign.model.service.inter;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Lists;
import com.huawang.business.command.CommandAddType;
import com.huawang.business.command.CommandParameter;
import com.huawang.business.constants.*;
import com.huawang.business.dto.*;
import com.huawang.business.dto.diagram.CustomizeColumnDTO;
import com.huawang.business.dto.graph.ModelInfo;
import com.huawang.business.dto.project.Project;
import com.huawang.business.dto.property.AddModelItem;
import com.huawang.business.dto.property.ItemInfo;
import com.huawang.business.dto.relation.RelationCriterionDTO;
import com.huawang.business.exception.AbortExecutionException;
import com.huawang.business.service.judge.BusinessJudgeService;
import com.huawang.business.service.model.base.*;
import com.huawang.business.service.model.core.*;
import com.huawang.business.service.model.core.project.ProjectManager;
import com.huawang.business.service.model.core.property.SelectedElementCheck;
import com.huawang.business.service.transaction.TransactionServiceImpl;
import com.huawang.business.util.InstanceVoUtils;
import com.huawang.business.vo.*;
import com.huawang.core.definition.mof.UMLDefinitionConstants;
import com.huawang.core.definition.mof.cmof.reflection.impl.BasicRElement;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import com.huawang.core.definition.mof.util.SnowflakeIdWorkerUtil;
import com.huawang.core.mof.persistence.dao.dos.PageResponseServiceDO;
import com.huawang.core.semantics.constants.ModelPackageNameConstants;
import com.huawang.core.semantics.constants.RelationConstraints;
import com.huawang.core.semantics.constants.TypeEnum;
import com.huawang.core.semantics.entity.queryResult.MofResultContainer;
import com.huawang.core.semantics.entity.queryResult.QueryPropertyForm;
import com.huawang.core.semantics.entity.script.ElementType;
import com.huawang.core.semantics.entity.transaction.LocalTransaction;
import com.huawang.core.semantics.exception.LocalTransactionNotStartException;
import com.huawang.core.semantics.exception.TransactionNotExistingException;
import com.huawang.mdesign.model.service.config.annotations.MofTransactional;
import com.huawang.mdesign.model.service.constant.SyncRuleProperty;
import com.huawang.mdesign.model.service.constant.UAFDefinitionConstants;
import com.huawang.mdesign.model.service.dto.*;
import com.huawang.mdesign.model.service.inter.override.UAFPropertyManager;
import com.huawang.mdesign.model.service.util.LogUtil;
import com.huawang.mdesign.model.service.vo.*;
import com.huawang.mdesign.model.service.vo.errorinfo.ModelErrorInfoVo;
import com.huawang.mdesign.model.service.vo.errorinfo.tips.SyncFailTip;
import com.huawang.mdesign.model.service.vo.errorinfo.util.TipConstant;
import com.huawang.mdesign.model.service.vo.selectelementitem.SelectElementItem;
import com.huawang.mdesign.model.service.vo.selectelementitem.SelectStereotypeItem;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.huawang.business.constants.ModelActionName.ADD_MODEL;
import static com.huawang.business.constants.ModelActionName.UPDATE_MODEL;

@Service
@Primary
@Slf4j
public class PropertyService {

    @Autowired
    private ProjectManager projectManager;

    @Autowired
    private UAFPropertyManager propertyManager;

    @Autowired
    private ModelManagerConfig managerConfig;

    @Autowired
    private UmlService umlService;

    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private InternalSpecificationService internalSpecificationService;

    @Autowired
    private SelectedElementCheck selectedElementCheck;

    @Autowired
    private InternalModelIconService internalModelIconService;

    @Autowired
    private InternalDiagramService internalDiagramService;

    @Autowired
    private ElementDefineService elementDefineService;

    @Autowired
    private ModelPropertyInfoService modelPropertyInfoService;

    @Autowired
    private InternalPropertyService internalPropertyService;

    @Autowired
    private ModelConstraintService modelConstraintService;

    @Autowired
    private ElementNameService elementNameService;

    @Autowired
    private InternalElementTree internalElementTree;

    @Autowired
    private TransactionServiceImpl transactionService;

    @Autowired
    private ModelManagerConfig modelManagerConfig;

    @Autowired
    private ElementModelInfoService elementModelInfoService;

    @Autowired
    private ElementPropertyService elementPropertyService;

    @Autowired
    private BusinessJudgeService businessJudgeService;

    @Autowired
    private ElementTypeService elementTypeService;

    private static final String HYPERLINK_CHECK_ALL_ELEMENTS = "checkAllElements";

    @Nullable
    public SelectElementNode buildSelectElementTree(final BuildSelectElementTreeDTO buildSelectElementTreeDto) {
        LogUtil.printSerializeOnlineLogs("buildSelectElementTree -> buildSelectElementTreeDto: ", buildSelectElementTreeDto);
        final String projectId = buildSelectElementTreeDto.getProjectId();
        final MetaClassInstance instance = internalUmlService.fetchInstance(buildSelectElementTreeDto.getInstanceId(),
                projectId);
        if (instance == null) {
            return null;
        }

        List<MetaClassInstance> allInstance = propertyManager.checkMethod(instance, buildSelectElementTreeDto);

        boolean flag = StringUtils.equals(HYPERLINK_CHECK_ALL_ELEMENTS, buildSelectElementTreeDto.getCheckMethod());

        return internalElementTree.parseListToTree(projectId, allInstance, flag);
    }

    @NotNull
    public List<SelectElementItem> buildSelectElementList(final BuildSelectElementTreeDTO buildSelectElementTreeDto) {
        LogUtil.printSerializeOnlineLogs("buildSelectElementList -> buildSelectElementTreeDto: ", buildSelectElementTreeDto);
        final String projectId = buildSelectElementTreeDto.getProjectId();
        Project activeProject = projectManager.getProject(projectId);
        if (Objects.isNull(activeProject)) {
            return Collections.emptyList();
        }
        final String rootModelId = activeProject.getRootModel();
        final MetaClassInstance rootInstance = internalUmlService.fetchInstance(rootModelId, projectId);
        final MetaClassInstance instance = internalUmlService.fetchInstance(buildSelectElementTreeDto.getInstanceId(),
                projectId);
        if (rootInstance == null || instance == null) {
            return Collections.emptyList();
        }
        List<MetaClassInstance> allInstance = propertyManager.checkMethod(instance, buildSelectElementTreeDto);
        QueryPropertyForm newqueryPropertyForm = internalUmlService.getQueryPropertyForm(allInstance,
                Stream.of(UMLDefinitionConstants.NamedElement_name).collect(Collectors.toList()));
        MofResultContainer newMofResultContainer = internalUmlService.queryProperty(projectId, newqueryPropertyForm);
        return allInstance.stream().filter(it -> !internalUmlService.checkInstanceType(
                        projectId, it, UMLDefinitionConstants.InstanceSpecification)
                        || StringUtils.isNotEmpty(newMofResultContainer.queryStringProperty(it.getId(), UMLDefinitionConstants.NamedElement_name)))
                .sorted(Comparator.comparing(BusinessJudgeService::isCreatedBySystem))
                .map(it -> {
                    String name = newMofResultContainer.queryStringProperty(it.getId(), UMLDefinitionConstants.NamedElement_name);
                    return createSelectElementItem(projectId, it, name);
                }).collect(Collectors.toList());
    }

    @NotNull
    public SelectElementItem createSelectElementItem(final String projectId, final MetaClassInstance instance, String name) {
        LogUtil.printOnlineLogs("projectId: {}, instance: {}, name: {}", projectId, instance, name);
        SelectElementItem item = new SelectElementItem();
        item.setInstanceId(instance.getId());
        item.setName(name);
        item.setIcon(internalModelIconService.queryIcon(projectId, instance));
        item.setIsUserCreate(BusinessJudgeService.isCreatedInteractive(instance));
        return item;
    }

    @NotNull
    private List<SelectStereotypeItem> createSelectStereotypeItemBatch(final String projectId, final List<MetaClassInstance> instances) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, instances: {}", projectId, instances);
        Map<String, String> iconMap = modelPropertyInfoService.queryIconBatch(projectId, instances);
        Map<String, String> nameMap = elementNameService.fetchNameBatch(projectId, instances);
        Map<String, List<String>> metaClassMap = internalUmlService.queryMetaClassListBatch(projectId, instances);
        Map<String, List<String>> baseClassMap = internalUmlService.getBaseClassListBatch(projectId, instances);
        List<SelectStereotypeItem> result = new ArrayList<>();
        for (MetaClassInstance instance : instances) {
            SelectStereotypeItem item = new SelectStereotypeItem();
            item.setInstanceId(instance.getId());
            item.setName(nameMap.get(instance.getId()));
            item.setIcon(iconMap.get(instance.getId()));

            List<String> metaClassList = metaClassMap.get(instance.getId());
            item.setMetaclass(metaClassList);
            final List<String> baseClassIdList = baseClassMap.get(instance.getId());
            item.setIsDiagram(baseClassIdList.contains(UMLDefinitionConstants.Diagram) ||
                    baseClassIdList.contains(UMLDefinitionConstants.UMLDiagram));

            result.add(item);
        }
        return result;
    }

    /**
     * 针对属性值为valuespecification的属性特殊处理
     *
     * @param dto
     * @return
     */
    @Nullable
    @MofTransactional
    public ModelResultVo updatePropertyByValueSpecification(final ModifyPropertyByValueSpecificationDTO dto) {
        updatePropertyByValueSpecificationNoTx(dto);
        return null;
    }

    public void updatePropertyByValueSpecificationNoTx(final ModifyPropertyByValueSpecificationDTO dto) {
        LogUtil.printSerializeOnlineLogs("updatePropertyByValueSpecification -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final String instanceId = dto.getInstanceId();
        MetaClassInstance valueSpecification = internalSpecificationService.createValueSpecificationByType(
                projectId,
                dto.getMetaclass(),
                dto.getValue(),
                dto.getExtraValue(),
                dto.getValueSpecificationId());
        //同一个valueSpecification重复设置到属性上，会导致里面的value被删除，所以不进行设置
        if (!Objects.equals(valueSpecification.getId(), dto.getValueSpecificationId())) {
            umlService.updateModel(projectId, instanceId, dto.getKey(), valueSpecification);
        }

        if (dto.getKey().equals(UMLDefinitionConstants.InteractionUse_argument) || dto.getKey().equals(UMLDefinitionConstants.Message_argument)) {
            umlService.updateModel(projectId, valueSpecification.getId(), UMLDefinitionConstants.Element_owner, internalUmlService.fetchInstance(instanceId, projectId));
        }
    }

    @NotNull
    public RowElementTypeVo queryElementsAndStereotypes(final String projectId,
                                                        final String instanceId) {
        LogUtil.printOnlineLogs("queryElementsAndStereotypes -> projectId: {}, instanceId: {}", projectId, instanceId);
        RowElementTypeVo rowElementTypeVo = new RowElementTypeVo();
        List<MetaClassInstance> metaClassInstances = new ArrayList<>();
        List<MetaClassInstance> stereotypes = new ArrayList<>();
        if (StringUtils.isNotBlank(instanceId)) {
            final MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
            if (internalUmlService.checkInstanceType(projectId, instance,
                    UMLDefinitionConstants.TableAndMatrix_BlackBoxICDTable)) {
                stereotypes = getStereotypesOfBlackBoxICDTable(projectId, metaClassInstances);
            } else if (internalUmlService.checkInstanceType(projectId, instance,
                    UMLDefinitionConstants.TableAndMatrix_PartICDTable)
                    || internalUmlService.checkInstanceType(projectId, instance,
                    UMLDefinitionConstants.TableAndMatrix_WhiteBoxICDTable)) {
                stereotypes = getStereotypesOfPartICDTableOrWhiteBoxICDTable(projectId, metaClassInstances);
            } else {
                log.info("模型{}不为黑盒ICD、白盒ICD或部件ICD, 无需初始化metaClass和stereotypes", instanceId);
            }
        }
        if (CollectionUtils.isEmpty(stereotypes) && CollectionUtils.isEmpty(metaClassInstances)) {
            // 获取元类模型的列表
            metaClassInstances.addAll(internalUmlService.queryAllMetaClassMetaClassInstance(projectId));
            // 获取构造型模型的列表
            stereotypes.addAll(internalUmlService.queryAllMetaStereotypeMetaClassInstance(projectId));
        }

        rowElementTypeVo = elementTypeService.queryAllElementType(projectId, metaClassInstances, stereotypes);
        return rowElementTypeVo;
    }


    private List<MetaClassInstance> getStereotypesOfPartICDTableOrWhiteBoxICDTable(String projectId, List<MetaClassInstance> metaClassInstances) {
        metaClassInstances.add(internalUmlService.fetchInstance(UMLDefinitionConstants.Connector, projectId));
        final List<String> sts = Stream.of(UMLDefinitionConstants.SysML_BindingConnector).collect(Collectors.toList());
        return getStereotypes(projectId, metaClassInstances, UMLDefinitionConstants.Connector, sts);
    }

    private List<MetaClassInstance> getStereotypesOfBlackBoxICDTable(String projectId, List<MetaClassInstance> metaClassInstances) {
        metaClassInstances.add(internalUmlService.fetchInstance(UMLDefinitionConstants.Port, projectId));
        final List<String> sts = Stream.of(UMLDefinitionConstants.SysML_ProxyPort,
                UMLDefinitionConstants.SysML_FullPort, UMLDefinitionConstants.SysML_FlowPort,
                UMLDefinitionConstants.Customization_ConstraintParameter).collect(Collectors.toList());
        return getStereotypes(projectId, metaClassInstances, UMLDefinitionConstants.Port, sts);
    }

    private List<MetaClassInstance> getStereotypes(String projectId, List<MetaClassInstance> metaClassInstances, String metaClass, List<String> initialSts) {
        LogUtil.printOnlineLogs("getStereotypes -> projectId: {}, metaClassInstances: {}", projectId, metaClassInstances);
        List<MetaClassInstance> stereotypeMetaClassInstanceList = internalUmlService.queryAllMetaStereotypeMetaClassInstance(projectId);

        stereotypeMetaClassInstanceList.forEach(e -> {
            List<String> selfBasePropertyList = internalUmlService.getSelfBasePropertyList(projectId, e);
            String metaClassValue = CollectionUtils.isNotEmpty(selfBasePropertyList) ? selfBasePropertyList.get(0) : null;
            if (metaClass.equals(metaClassValue)) {
                initialSts.add(e.getId());
            }
        });

        return internalUmlService.fetchInstanceByIds(initialSts, projectId);
    }

    /**
     * 获取图标的元类
     *
     * @param projectId
     * @return
     */
    @NotNull
    public RowElementTypeVo queryDiagramStereotypes(final String projectId) {
        LogUtil.printOnlineLogs("projectId: {}", projectId);
        List<MetaClassInstance> stereotypes = internalUmlService.queryAllMetaStereotypeMetaClassInstance(projectId)
                .stream().filter(it -> {
                    Set<String> allType = internalUmlService.getMetaGivenTypes(projectId, it.getId());
                    return allType.contains(UMLDefinitionConstants.Diagram);
                }).collect(Collectors.toList());
        return elementTypeService.queryAllElementType(projectId, new ArrayList<>(),
                stereotypes);
    }
    @NotNull
    public List<ElementType> getCustomizationElementTypes(String projectId, List<MetaClassInstance> stereotypes) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, stereotypes: {}", projectId, stereotypes);
        List<MetaClassInstance> customizationStereotype = new ArrayList<>();
        List<ElementType> elementTypesOfStereotype = new ArrayList<>();
        Project project = projectManager.getValidProject(projectId);
        stereotypes.forEach(stereotype -> {
            ModelInfo info = managerConfig.getModelInfoConfig().get(
                    elementModelInfoService.getModelInfoKeyByStereotypeId(stereotype.getId()));
            if (Objects.nonNull(info)) {
                if(CollectionUtils.isEmpty(info.getSpecifications()) || info.getSpecifications().contains(project.getProjectSpecification())) {
                    ElementType elementType = makeElementType(stereotype, info);
                    elementTypesOfStereotype.add(elementType);
                }
            } else {
                customizationStereotype.add(stereotype);
            }
        });
        List<ElementType> customizationElementTypes = new ArrayList<>();
        modelPropertyInfoService.createModelPropertyInfoAndTypeList(projectId, customizationStereotype,
                        Stream.of(UMLDefinitionConstants.Element_appliedStereotype, UMLDefinitionConstants.NamedElement_name)
                                .collect(Collectors.toList()))
                .forEach(model -> {
                    ElementType elementType = new ElementType();
                    elementType.setIcon(managerConfig.getModelInfoConfig().get(UMLDefinitionConstants.Stereotype).getIcon());
                    elementType.setName(model.queryStringValue(UMLDefinitionConstants.NamedElement_name));
                    elementType.setEnName(model.queryStringValue(UMLDefinitionConstants.NamedElement_name));
                    elementType.setValue(model.getInstance().getId());
                    customizationElementTypes.add(elementType);
                });
        elementTypesOfStereotype.addAll(customizationElementTypes);
        return elementTypesOfStereotype;
    }
    @NotNull
    public static ElementType makeElementType(MetaClassInstance model, ModelInfo info) {
        LogUtil.printSerializeOnlineLogs("model: {}, info: {}", model, info);
        ElementType elementType = new ElementType();
        String icon = info.getIcon();
        String name = info.getCnName();
        String id = model.getId();
        elementType.setIcon(icon);
        elementType.setName(name);
        elementType.setValue(id);
        elementType.setEnName(info.getEnName());
        return elementType;
    }

    @NotNull
    public RowElementTypeVo showElementsAndStereotypesByType(final String projectId, final Boolean isQueryRelation) {
        LogUtil.printOnlineLogs("projectId: {}, isQueryRelation: {}", projectId, isQueryRelation);
        RowElementTypeVo rowElementTypeVo = new RowElementTypeVo();
        // 图/表/矩阵不可选择
        List<MetaClassInstance> metaClassInstances = internalUmlService.queryAllMetaClassMetaClassInstance(projectId).
                stream().filter(it -> !it.getId().contains("Table") && !it.getId().contains("Map") && !it.getId().contains("Diagram") && !it.getId().contains("Matrix")).collect(Collectors.toList());
        List<MetaClassInstance> stereotypes = internalUmlService.queryAllMetaStereotypeMetaClassInstance(projectId).
                stream().filter(it -> !it.getId().contains("Table") && !it.getId().contains("Map") && !it.getId().contains("Diagram") && !it.getId().contains("Matrix")).collect(Collectors.toList());
        // 根据isQueryRelation过滤关系类型和非关系类型
        List<MetaClassInstance> relationTypeInstances = internalUmlService.fetchInstanceByIds(RelationConstraints.RELATION_TYPES,
                projectId);
        metaClassInstances = BooleanUtils.isTrue(isQueryRelation) ? new ArrayList<>(CollectionUtils.intersection(metaClassInstances, relationTypeInstances)) :
                new ArrayList<>(CollectionUtils.subtract(metaClassInstances, relationTypeInstances));
        Map<String, Set<String>> givenTypes = internalUmlService.getGivenTypes(projectId, stereotypes);
        stereotypes =
                stereotypes.stream().filter(it -> BooleanUtils.isTrue(isQueryRelation) != Collections.disjoint(givenTypes.get(it.getId()), RelationConstraints.RELATION_TYPES)).collect(Collectors.toList());
        rowElementTypeVo = elementTypeService.queryAllElementType(projectId, metaClassInstances, stereotypes);
        return rowElementTypeVo;
    }

    @NotNull
    public ElementTypeVo queryAllElements(String projectId) {
        LogUtil.printOnlineLogs("queryAllElements -> projectId: ", projectId);
        ElementTypeVo elementTypeVo = new ElementTypeVo();
        List<ElementType> elementTypes = internalDiagramService.queryAllElementType(projectId);
        elementTypeVo.setElements(elementTypes);
        return elementTypeVo;
    }

    @NotNull
    public AssociateTypeVo queryAllRelations(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("queryAllRelations -> projectId: {}, instanceId: {}", projectId, instanceId);
        AssociateTypeVo associateTypeVo = new AssociateTypeVo();
        List<ElementType> elementTypes = new ArrayList<>();
        MetaClassInstance diagramInstance = internalUmlService.fetchInstance(instanceId, projectId);
        // 获取关系模型的列表
        List<MetaClassInstance> associateInstances;
        if (diagramInstance != null && internalUmlService.checkInstanceType(projectId, diagramInstance,
                UMLDefinitionConstants.TableAndMatrix_RequirementRelationMap)) {
            associateInstances = internalUmlService.fetchInstanceByIds(ModelConstantURI.MAP_RELATION_TYPE, projectId);
        } else {
            associateInstances =
                    internalUmlService.fetchInstanceByIds(internalUmlService.queryAllRelationType(projectId), projectId);
        }

        associateInstances.forEach(associateInstance -> {
            ElementType elementType = new ElementType();
            ModelInfo info = internalUmlService.fetchSpecificModelInfoValue(projectId, associateInstance);
            if (Objects.nonNull(info)) {
                String icon = info.getIcon();
                String name = info.getCnName();
                String id = associateInstance.getId();
                elementType.setIcon(icon);
                elementType.setName(name);
                elementType.setEnName(info.getEnName());
                elementType.setValue(id);
                elementTypes.add(elementType);
            }
        });
        associateTypeVo.setAssociates(elementTypes);
        return associateTypeVo;
    }

    @NotNull
    public ElementTypeVo queryElements(String projectId) {
        LogUtil.printOnlineLogs("queryElements -> projectId: ", projectId);
        ElementTypeVo elementTypeVo = new ElementTypeVo();
        List<ElementType> elementTypesOfMetaClass = new ArrayList<>();

        // 获取元类模型的列表
        List<MetaClassInstance> metaClassInstances = internalUmlService.getSysCreatedStereotypeByProfileID(projectId,
                ModelPackageNameConstants.UML);
        metaClassInstances.forEach(model -> {
            ElementType elementType = new ElementType();
            ModelInfo info = managerConfig.getModelInfoConfig().get(model.getId());
            if (Objects.nonNull(info)) {
                String icon = info.getIcon();
                String name = info.getCnName();
                elementType.setIcon(icon);
                elementType.setName(name);
                elementType.setEnName(info.getEnName());
                elementType.setValue(model.getId());
                elementTypesOfMetaClass.add(elementType);
            }
        });
        elementTypeVo.setElements(elementTypesOfMetaClass);
        return elementTypeVo;
    }

    /**
     * @param modifyPropertyByValueSpecificationDto
     * @return com.huawang.mdesign.model.service.vo.ModelResultVo
     * @description 元素的属性值是一个Constraint时，修改其值，实际是修改Constraint的Specification，
     * Constraint的Specification是一个ValueSpecification
     * @author baibf
     * @date 2022/5/25
     */
    @NotNull
    public ModelResultVo createPropertyValueIsConstraint(ModifyPropertyByValueSpecificationDTO
                                                                 modifyPropertyByValueSpecificationDto) {
        LogUtil.printSerializeOnlineLogs("modifyPropertyByValueSpecificationDto: ", modifyPropertyByValueSpecificationDto);
        final String projectId = modifyPropertyByValueSpecificationDto.getProjectId();
        final ModelResultVo modelResultVo = new ModelResultVo();
        LocalTransaction transaction = transactionService.createTransaction(projectId, ModelActionName.UPDATE_PROPERTY);
        MetaClassInstance instance = internalUmlService.fetchInstance(modifyPropertyByValueSpecificationDto.getInstanceId(),
                projectId);
        try {
            MetaClassInstance resultInstance = createConstraintSpecification(instance,
                    modifyPropertyByValueSpecificationDto);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(resultInstance.getId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.PROPERTY_UPDATE_ERROR, e);
        }
        return modelResultVo;
    }

    @NotNull
    private MetaClassInstance createConstraintSpecification(MetaClassInstance instance,
                                                            ModifyPropertyByValueSpecificationDTO modifyPropertyByValueSpecificationDto) {
        LogUtil.printSerializeOnlineLogs("instance: {}, modifyPropertyByValueSpecificationDto: {}", instance,
                modifyPropertyByValueSpecificationDto);
        final String projectId = modifyPropertyByValueSpecificationDto.getProjectId();
        MetaClassInstance constraintInstance;
        if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.InteractionOperand)) {
            constraintInstance = internalUmlService.queryInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.InteractionOperand_guard);
            if (constraintInstance == null) {
                CommandParameter interactionConstraintParameter = CommandParameter.builder()
                        .projectId(projectId)
                        .typeId(UMLDefinitionConstants.InteractionConstraint)
                        .type(CommandAddType.MODEL)
                        .parentId(modifyPropertyByValueSpecificationDto.getInstanceId())
                        .instanceId(ModelConstantURI.initInstanceId())
                        .build();
                constraintInstance = umlService.addModel(interactionConstraintParameter);
                umlService.updateModel(projectId, instance.getId(), UMLDefinitionConstants.InteractionOperand_guard,
                        constraintInstance);
            }
        } else if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Transition)) {
            constraintInstance = internalUmlService.queryInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.Transition_guard);
            if (constraintInstance == null) {
                CommandParameter constraintParameter = CommandParameter.builder()
                        .projectId(projectId)
                        .typeId(UMLDefinitionConstants.Constraint)
                        .type(CommandAddType.MODEL)
                        .parentId(modifyPropertyByValueSpecificationDto.getInstanceId())
                        .instanceId(ModelConstantURI.initInstanceId())
                        .build();
                constraintInstance = umlService.addModel(constraintParameter);
                umlService.updateModel(projectId, instance.getId(), UMLDefinitionConstants.Transition_guard, constraintInstance);
            }
        } else if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.StateInvariant)) {
            constraintInstance = internalUmlService.queryInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.StateInvariant_invariant);
            if (Objects.isNull(constraintInstance)) {
                CommandParameter constraintParameter = CommandParameter.builder()
                        .projectId(projectId)
                        .typeId(UMLDefinitionConstants.Constraint)
                        .type(CommandAddType.MODEL)
                        .parentId(modifyPropertyByValueSpecificationDto.getInstanceId())
                        .instanceId(ModelConstantURI.initInstanceId())
                        .build();
                constraintInstance = umlService.addModel(constraintParameter);
                umlService.updateModel(projectId, instance.getId(), UMLDefinitionConstants.StateInvariant_invariant, constraintInstance);
            }
        } else if (internalUmlService.checkInstanceType(projectId, instance, UMLDefinitionConstants.Message)) {
            constraintInstance = internalUmlService.queryInstanceProperty(projectId, instance,
                    UMLDefinitionConstants.Message_guard);
            if (Objects.isNull(constraintInstance)) {
                CommandParameter constraintParameter = CommandParameter.builder()
                        .projectId(projectId)
                        .typeId(UMLDefinitionConstants.Constraint)
                        .type(CommandAddType.MODEL)
                        .parentId(modifyPropertyByValueSpecificationDto.getInstanceId())
                        .instanceId(ModelConstantURI.initInstanceId())
                        .build();
                constraintInstance = umlService.addModel(constraintParameter);
                umlService.updateModel(projectId, instance.getId(),
                        UMLDefinitionConstants.Message_guard, constraintInstance);
            }
        } else {
            throw AbortExecutionException.build(ErrorCode.INSTANCE_TYPE_ERROR);
        }

        MetaClassInstance valueSpecificationInstance = internalSpecificationService.createValueSpecificationByType(
                projectId,
                modifyPropertyByValueSpecificationDto.getMetaclass(),
                modifyPropertyByValueSpecificationDto.getValue(),
                modifyPropertyByValueSpecificationDto.getExtraValue(),
                modifyPropertyByValueSpecificationDto.getValueSpecificationId());
        umlService.updateModel(projectId, constraintInstance.getId(), UMLDefinitionConstants.Constraint_specification,
                valueSpecificationInstance);
        return constraintInstance;
    }

    @NotNull
    public ModelResultVo modifySlotValue(String projectId, String slotId, String value) {
        LogUtil.printOnlineLogs("projectId: {}, slotId: {}, value: {}", projectId, slotId, value);
        MetaClassInstance slot = internalUmlService.fetchInstance(slotId, projectId);
        if (slot == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        QueryPropertyForm newqueryPropertyForm = internalUmlService.getQueryPropertyForm(slot,
                Stream.of(UMLDefinitionConstants.Slot_definingFeature, UMLDefinitionConstants.Slot_value, UMLDefinitionConstants.Slot_owningInstance
                ).collect(Collectors.toList()));
        MofResultContainer newMofResultContainer = internalUmlService.queryProperty(projectId, newqueryPropertyForm);

        MetaClassInstance property = newMofResultContainer.queryInstanceProperty(slot.getId(), UMLDefinitionConstants.Slot_definingFeature);
        if (property == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        final List<MetaClassInstance> slotValues = newMofResultContainer.queryListInstanceProperty(slot.getId(), UMLDefinitionConstants.Slot_value);
        if (CollectionUtils.isEmpty(slotValues)) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }

        // 校验输入的slot值与其类型是否匹配
        if (!internalSpecificationService.validateType(projectId, value, property)) {
            throw AbortExecutionException.build(ErrorCode.TYPE_MISMATCH);
        }

        MetaClassInstance owningInstance = newMofResultContainer.queryInstanceProperty(slot.getId(), UMLDefinitionConstants.Slot_owningInstance);
        if (Objects.isNull(owningInstance)) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }


        final ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(
                projectId, ModelActionName.UPDATE_PROPERTY);

        try {
            MetaClassInstance applyInstance = internalUmlService.queryInstanceProperty(projectId, owningInstance,
                    UMLDefinitionConstants.A_appliedStereotypeInstance_owner_owner);
            if (applyInstance != null) {
                ModifyPropertyDTO propertyDto = new ModifyPropertyDTO();
                propertyDto.setKey(property.getId());
                propertyDto.setValue(Collections.singletonList(value));
                propertyDto.setDataType(TypeEnum.STRING.getName());
                propertyDto.setInstanceId(applyInstance.getId());
                propertyDto.setIsMultiplicity(false);
                propertyDto.setProjectId(projectId);
                propertyManager.updatePropertyValue(propertyDto);
            } else {
                MetaClassInstance owner = internalUmlService.queryInstanceProperty(projectId, owningInstance,
                        UMLDefinitionConstants.Element_owner);
                if (Objects.isNull(owner)) {
                    throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
                }

                internalSpecificationService.setBaseValue(projectId, slotValues.get(0), value);
            }
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(slotId);
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.PROPERTY_UPDATE_ERROR, e);
        }
        return modelResultVo;
    }

    @NotNull
    public List<SelectStereotypeItem> queryAppliedStereotypeList(BuildSelectElementTreeDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryAppliedStereotypeList -> dto: ", dto);
        final String projectId = dto.getProjectId();
        List<MetaClassInstance> instances = selectedElementCheck.checkElementAppliedStereotype(dto);
        return createSelectStereotypeItemBatch(projectId, instances);
    }

    @NotNull
    public List<SelectStereotypeItem> queryMultiAppliedStereotypeList(QueryMultiAppliedStereotypeDTO dto) {
        LogUtil.printSerializeOnlineLogs("queryMultiAppliedStereotypeList -> dto: ", dto);
        final String projectId = dto.getProjectId();
        List<MetaClassInstance> instances = selectedElementCheck.checkElementAppliedStereotype(dto.getProjectId(),
                dto.getInstanceIds());
        return createSelectStereotypeItemBatch(projectId, instances);
    }

    @NotNull
    public List<String> queryElementDisplay(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("queryElementDisplay -> projectId: {}, instanceId: {}", projectId, instanceId);
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            return Collections.emptyList();
        }
        Set<String> typeUris = internalUmlService.getGivenTypes(projectId, instance);

        return getMenu(typeUris, false);
    }

    private @NotNull List<String> getMenu(Set<String> typeUris, boolean isBatch) {
        List<String> displayLabel = new ArrayList<>();
        if ((typeUris.contains(UMLDefinitionConstants.EncapsulatedClassifier)
                || typeUris.contains(UMLDefinitionConstants.StructuralFeature)
                || typeUris.contains(UMLDefinitionConstants.SysMLInternalBlockDiagram)
                || typeUris.contains(UMLDefinitionConstants.SysMLParametricDiagram))
                && !typeUris.contains(UMLDefinitionConstants.SysML_Requirement)
                && !typeUris.contains(UMLDefinitionConstants.SysML_ConstraintBlock)
                && !typeUris.contains(UMLDefinitionConstants.Customization_Legend)
                && !typeUris.contains(UMLDefinitionConstants.SysML_ConnectorProperty)
                && !typeUris.contains(UMLDefinitionConstants.SysML_ParticipantProperty)
                && !typeUris.contains(UMLDefinitionConstants.SysML_FlowProperty)
                && !typeUris.contains(UMLDefinitionConstants.Customization_ValueProperty)
                && !typeUris.contains(UMLDefinitionConstants.SysML_BoundReference)) {
            // 隐藏所有端口
            displayLabel.add("hidePorts");
            // 显示所有端口
            displayLabel.add("showInternalPort");
            // 显示端口/部件
            displayLabel.add("showPartsAndPorts");
        }
        if (typeUris.contains(UMLDefinitionConstants.SysML_ConstraintBlock)
                || typeUris.contains(UMLDefinitionConstants.SysML_ConnectorProperty)
                || typeUris.contains(UMLDefinitionConstants.SysML_ParticipantProperty)
                || typeUris.contains(UMLDefinitionConstants.SysML_FlowProperty)
                || typeUris.contains(UMLDefinitionConstants.Customization_ValueProperty)
                || typeUris.contains(UMLDefinitionConstants.SysML_BoundReference)
        ) {
            displayLabel.add("showPartsAndPorts");
        }
        if (typeUris.contains(UMLDefinitionConstants.Element)
                && !typeUris.contains(UMLDefinitionConstants.Lifeline)
                && !typeUris.contains(UMLDefinitionConstants.Customization_Legend)
                && !typeUris.contains(UMLDefinitionConstants.Transition)
                && !typeUris.contains(UMLDefinitionConstants.Message)
                && !typeUris.contains(UMLDefinitionConstants.DurationConstraint)
                && !typeUris.contains(UMLDefinitionConstants.ActivityEdge)) {
            // 显示关系连线
            displayLabel.add("showRelationEdge");
            if (isBatch) {
                displayLabel.add("batchShowRelationEdge");
            }
        }
        if (typeUris.contains(UMLDefinitionConstants.NamedElement)
                && !typeUris.contains(UMLDefinitionConstants.Relationship)
                && !typeUris.contains(UMLDefinitionConstants.Connector)
                && !typeUris.contains(UMLDefinitionConstants.Transition)
                && !typeUris.contains(UMLDefinitionConstants.Message)
                && !typeUris.contains(UMLDefinitionConstants.Lifeline)
                && !typeUris.contains(UMLDefinitionConstants.Customization_Legend)
                && !typeUris.contains(UMLDefinitionConstants.DurationConstraint)
                && !typeUris.contains(UMLDefinitionConstants.ActivityEdge)) {
            // 显示关联元素
            displayLabel.add("showRelatedElement");
        }
        if (typeUris.contains(UMLDefinitionConstants.Package)) {
            // 显示内部元素
            displayLabel.add("showInnerItem");
        }
        if (typeUris.contains(UMLDefinitionConstants.InputPin)
                || typeUris.contains(UMLDefinitionConstants.OutputPin)) {
            //显示多重性
            displayLabel.add("showTypeAndMultiplicity");
        }
        return displayLabel;
    }

    @NotNull
    public List<String> queryAppliedStereotypeListByType(String projectId, String typeId) {
        LogUtil.printOnlineLogs("projectId: {}, typeId: {}", projectId, typeId);
        MetaClassInstance metaClassOrStereotypeInstance = internalUmlService.fetchInstance(typeId, projectId);
        if (Objects.isNull(metaClassOrStereotypeInstance)) {
            log.error("元模型查找失败");
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        String metaClassId = metaClassOrStereotypeInstance.getId();
        if (!internalUmlService.isOnlyMetaClass(projectId, metaClassOrStereotypeInstance)) {
            List<String> metaClassList = internalUmlService.getSelfBasePropertyList(projectId,
                    metaClassOrStereotypeInstance);
            if (CollectionUtils.isEmpty(metaClassList)) {
                log.error("构造型找不到元类");
                throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
            }
            metaClassId = metaClassList.get(0);
        }

        return internalUmlService.getMetaClassApplicableStereotype(projectId,
                metaClassId);
    }

    @NotNull
    public Boolean checkElementType(String projectId, String instanceId, String type) {
        LogUtil.printOnlineLogs("projectId: {}, instanceId: {}, type: {}", projectId, instanceId, type);
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            return false;
        }

        return internalUmlService.checkInstanceType(projectId, instance, type);
    }

    @NotNull
    public List<String> queryElementAllMataClass(String projectId, String instanceId) {
        LogUtil.printOnlineLogs("queryElementAllMataClass -> projectId: {}, instanceId: {}", projectId, instanceId);
        MetaClassInstance instance = internalUmlService.fetchInstance(instanceId, projectId);
        if (Objects.isNull(instance)) {
            return Collections.emptyList();
        }

        return internalUmlService.getGeneralsCascade(projectId, instance.getMetaClass().getId()).stream()
                .map(MetaClassInstance::getId).collect(Collectors.toList());
    }

    @NotNull
    public PageResponseVo buildSelectElementsTreeWithPage(BuildSelectElementTreeDTO buildSelectElementTreeDto) {
        LogUtil.printSerializeOnlineLogs("buildSelectElementsTreeWithPage -> buildSelectElementTreeDto: ",
                buildSelectElementTreeDto);
        final String projectId = buildSelectElementTreeDto.getProjectId();
        List<MetaClassInstance> instances = propertyManager.checkMethodPage(buildSelectElementTreeDto);
        List<SelectElementNode> selectElementNodes = internalElementTree.parseListToNodeList(projectId, instances);
        PageResponseVo result = new PageResponseVo();
        result.setSelectElementNodes(selectElementNodes);
        result.setPage(buildSelectElementTreeDto.getPage());
        result.setSize(buildSelectElementTreeDto.getSize());
        return result;
    }

    @NotNull
    public PageResponseVo queryElementByKeywordWithPage(BuildSelectElementTreeDTO buildSelectElementTreeDto) {
        LogUtil.printSerializeOnlineLogs("queryElementByKeywordWithPage -> buildSelectElementTreeDto: ",
                buildSelectElementTreeDto);
        final String projectId = buildSelectElementTreeDto.getProjectId();
        PageResponseServiceDO pageResponseServiceDO = propertyManager.checkMethodPageWithKeyword(buildSelectElementTreeDto);
        List<SelectElementNode> selectElementNodes = internalElementTree.parseListToNodeList(
                projectId, pageResponseServiceDO.getMetaClassInstanceList());
        PageResponseVo result = new PageResponseVo();
        result.setSelectElementNodes(selectElementNodes);
        result.setPage(buildSelectElementTreeDto.getPage());
        result.setSize(buildSelectElementTreeDto.getSize());
        result.setCount(pageResponseServiceDO.getCount());
        return result;
    }

    @NotNull
    public PageResponseVo fetchInstancesWithKeyword(SelectInstanceByKeywordDTO dto) {
        PageResponseServiceDO pageResponseServiceDO = internalUmlService.fetchInstancesWithKeyword(
                dto.getProjectId(), dto.getClassifierIds(), new HashSet<>(),
                dto.getPage(), dto.getSize(), dto.getKeyword(), false);
        List<SelectElementNode> selectElementNodes = internalElementTree.parseListToNodeList(dto.getProjectId(),
                pageResponseServiceDO.getMetaClassInstanceList());
        PageResponseVo result = new PageResponseVo();
        result.setSelectElementNodes(selectElementNodes);
        result.setPage(dto.getPage());
        result.setSize(dto.getSize());
        result.setCount(pageResponseServiceDO.getCount());
        return result;
    }

    @NotNull
    public PageResponseVo queryElementByKeywordWithPageBatch(BuildSelectElementTreeBatchDTO buildSelectElementTreeBatchDTO) {
        LogUtil.printSerializeOnlineLogs("buildSelectElementTreeBatchDTO: ", buildSelectElementTreeBatchDTO);
        final String projectId = buildSelectElementTreeBatchDTO.getProjectId();
        PageResponseServiceDO pageResponseServiceDO = propertyManager.checkMethodPageWithKeywordBatch(buildSelectElementTreeBatchDTO);
        List<SelectElementNode> selectElementNodes = internalElementTree.parseListToNodeList(
                projectId, pageResponseServiceDO.getMetaClassInstanceList());
        PageResponseVo result = new PageResponseVo();
        result.setSelectElementNodes(selectElementNodes);
        result.setPage(buildSelectElementTreeBatchDTO.getPage());
        result.setSize(buildSelectElementTreeBatchDTO.getSize());
        result.setCount(pageResponseServiceDO.getCount());
        return result;

    }

    @NotNull
    public List<CheckValidPropertyValueVo> checkValidPropertyValue(CheckValidPropertyValueDTO dto) {
        LogUtil.printSerializeOnlineLogs("checkValidPropertyValue -> dto: ", dto);
        if (CollectionUtils.isEmpty(dto.getIds())) {
            return Collections.emptyList();
        }
        return propertyManager.checkValidPropertyValue(dto);
    }

    @NotNull
    public List<CheckValidPropertyValueVo> checkValidPropertyValueBatch(CheckValidPropertyValueBatchDTO dto) {
        if (CollectionUtils.isEmpty(dto.getIds())) {
            return Collections.emptyList();
        }
        return propertyManager.checkValidPropertyValueBatch(dto);
    }


    /**
     * 查询指定模型的子集属性
     *
     * @param dto
     * @return
     */
    @NotNull
    public SubPropertyTreeVo querySubPropertiesByParams(SubPropertyParamDTO dto) {
        LogUtil.printSerializeOnlineLogs("querySubPropertiesByParams -> dto: ", dto);
        SubPropertyTreeVo subPropertyTreeVo = new SubPropertyTreeVo();
        String projectId = dto.getProjectId();

        String selectedPropertyId = dto.getPropertyId();
        MetaClassInstance selectedProperty = internalUmlService.fetchInstance(selectedPropertyId, projectId);

        MetaClassInstance parentInstance = internalUmlService.queryInstanceProperty(projectId, selectedProperty, UMLDefinitionConstants.Element_owner);
        if (parentInstance == null) {
            return subPropertyTreeVo;
        }

        QueryPropertyForm newqueryPropertyForm = internalUmlService.getQueryPropertyForm(parentInstance,
                Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.Class_ownedAttribute
                ).collect(Collectors.toList()));
        MofResultContainer newMofResultContainer = internalUmlService.queryProperty(projectId, newqueryPropertyForm);
        String parentId = parentInstance.getId();
        subPropertyTreeVo.setId(parentId);
        subPropertyTreeVo.setIcon(internalModelIconService.queryIcon(projectId, parentInstance));
        String parentName = newMofResultContainer.queryStringProperty(parentInstance.getId(), UMLDefinitionConstants.NamedElement_name);
        subPropertyTreeVo.setName(parentName);
        subPropertyTreeVo.setType(parentInstance.getMetaClass().getName());
        final List<MetaClassInstance> ownedProperties = newMofResultContainer.queryListInstanceProperty(parentInstance.getId(),
                        UMLDefinitionConstants.Class_ownedAttribute).stream()
                .filter(property -> !property.getId().startsWith("base_"))
                .collect(Collectors.toList());

        List<SubPropertyTreeVo> subPropertyVos = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(ownedProperties)) {
            List<MetaClassInstance> subProperties = internalUmlService.queryListInstanceProperty(projectId, selectedProperty,
                    UMLDefinitionConstants.Property_subsettedProperty);
            //求交集
            List<MetaClassInstance> sameProperties = (List<MetaClassInstance>) CollectionUtils.intersection(ownedProperties, subProperties);
            QueryPropertyForm queryPropertyForm = internalUmlService.getQueryPropertyForm(parentInstance,
                    Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.Property_subsettedProperty
                    ).collect(Collectors.toList()));
            MofResultContainer mofResultContainer = internalUmlService.queryProperty(projectId, queryPropertyForm);
            ownedProperties.stream().filter(property -> !property.getId().equals(selectedPropertyId)).forEach(property -> {
                SubPropertyTreeVo subPropertyVo = new SubPropertyTreeVo();
                subPropertyVo.setId(property.getId());

                subPropertyVo.setName(mofResultContainer.queryStringProperty(property.getId(), UMLDefinitionConstants.NamedElement_name));
                subPropertyVo.setIcon(internalModelIconService.queryIcon(projectId, property));
                subPropertyVo.setType(property.getMetaClass().getName());
                if (sameProperties.contains(property)) {
                    //本期不允许递归、嵌套设置子集属性（递归指：A的子集属性选择B进行subsets操作；
                    //然后B的子集属性选择A进行subsets操作；嵌套指A的子集属性是B、C进行subSets，D的子集属性是A的subSets操作）
                    List<MetaClassInstance> oppositeSubProperties = mofResultContainer.queryListInstanceProperty(property.getId(),
                            UMLDefinitionConstants.Property_subsettedProperty);
                    if (!oppositeSubProperties.contains(selectedProperty)) {
                        subPropertyVo.setChecked(true);
                    }
                }
                subPropertyVos.add(subPropertyVo);
            });
        }
        subPropertyTreeVo.setChildren(subPropertyVos);
        return subPropertyTreeVo;
    }

    /**
     * 根据被约束对象查询被约束的属性列表
     *
     * @param buildSelectElementTreeDto 被约束的对象信息。
     * @return
     */
    @Nullable
    public ConstraintPropertyNode queryConstrainedProps(BuildSelectElementTreeDTO buildSelectElementTreeDto) {
        LogUtil.printSerializeOnlineLogs("queryConstrainedProps -> buildSelectElementTreeDto: ", buildSelectElementTreeDto);
        // 查询被约束对象的属性以及继承过来的属性。
        final String projectId = buildSelectElementTreeDto.getProjectId();
        final MetaClassInstance instance = internalUmlService.fetchInstance(buildSelectElementTreeDto.getInstanceId(),
                projectId);
        if (instance == null) {
            return null;
        }

        List<MetaClassInstance> allInstance = propertyManager.checkMethod(instance, buildSelectElementTreeDto);

        boolean flag = StringUtils.equals(HYPERLINK_CHECK_ALL_ELEMENTS, buildSelectElementTreeDto.getCheckMethod());

        SelectElementNode selectElementNode = internalElementTree.parseListToTree(projectId, allInstance, flag);
        ConstraintPropertyNode root = new ConstraintPropertyNode();
        //从selectElementNode到ConstraintPropertyNode的转换。
        if (selectElementNode == null) {
            return null;
        }

        setConstraintPropertyNode(root, selectElementNode);
        return root;
    }

    /**
     * 递归转换节点树
     *
     * @param root              新节点树
     * @param selectElementNode 旧节点树
     */
    private static void setConstraintPropertyNode(ConstraintPropertyNode root, SelectElementNode selectElementNode) {
        LogUtil.printSerializeOnlineLogs("root: {}, selectElementNode: {}", root, selectElementNode);
        root.setSelectable(selectElementNode.getIsSelected());
        root.setInstanceId(selectElementNode.getInstanceId());
        List<ConstraintPropertyNode> children = new ArrayList<>();
        selectElementNode.getChildren().forEach(node -> {
            ConstraintPropertyNode child = new ConstraintPropertyNode();
            child.setSelectable(node.getIsSelected());
            child.setInstanceId(node.getInstanceId());
            children.add(child);
            root.setChildren(children);
            setConstraintPropertyNode(child, node);
        });
    }

    @NotNull
    public RelationCriterionDTO queryRelationCriterion(final String projectId, final String mapId, String type) {
        LogUtil.printSerializeOnlineLogs("projectId: {}, mapId: {}, type: {}", projectId, mapId, type);
        if (type == null) {
            // 兼容已有的追溯图查询关系类型接口逻辑
            type = UpdateRelationType.DIAGRAM.value();
        }
        return internalPropertyService.queryRelationCriterion(projectId, mapId, type);
    }

    /**
     * 新增关系属性
     *
     * @param relationCriterionDTO
     * @return
     */
    @NotNull
    public ModelResultVo newUpdateRelationCriterion(RelationCriterionDTO relationCriterionDTO) {
        LogUtil.printSerializeOnlineLogs("updateRelationCriterion -> dto: ", relationCriterionDTO);

        final String projectId = relationCriterionDTO.getProjectId();
        final MetaClassInstance relationMap = internalUmlService.fetchInstance(relationCriterionDTO.getInstanceId(), relationCriterionDTO.getProjectId());
        if (relationMap == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        return internalPropertyService.updateNewRelationCriterion(projectId, relationCriterionDTO);
    }

    /**
     * 查询关系属性
     *
     * @param projectId
     * @param type
     * @param instanceId
     * @param columnId
     * @return
     */
    public CustomizeColumnDTO newQueryRelationCriterion(@NotNull String projectId, @NotNull String type, @NotNull String instanceId, String columnId) {
        final MetaClassInstance relationMap = internalUmlService.fetchInstance(instanceId, projectId);
        if (relationMap == null) {
            throw AbortExecutionException.build(ErrorCode.MODEL_NO_EXIST);
        }
        LogUtil.printOnlineLogs("projectId: {}, tableId: {}, columnId: {}", projectId, instanceId, columnId);
        return internalPropertyService.newQueryRelationCriterion(projectId, type, instanceId, columnId);
    }

    @NotNull
    public CriterionTypesVo showCriterionTypes(String projectId) {
        LogUtil.printOnlineLogs("showCriterionTypes -> projectId: ", projectId);
        RowElementTypeVo rowElementTypeVo = queryElementsAndStereotypes(projectId, null);
        CriterionTypesVo criterionTypesVo = new CriterionTypesVo();
        List<ElementType> primitiveTypes = Stream.of(TypeEnum.BOOLEAN.getName(), TypeEnum.STRING.getName(),
                TypeEnum.REAL.getName(), TypeEnum.INTEGER.getName()).map(primitiveType -> {
            ElementType elementType = new ElementType();
            ModelInfo info = managerConfig.getModelInfoConfig().get(UMLDefinitionConstants.PrimitiveType);
            elementType.setValue(primitiveType);
            elementType.setIcon(info.getIcon());
            return elementType;
        }).collect(Collectors.toList());
        criterionTypesVo.setMetaClasses(rowElementTypeVo.getMetaClasses());
        criterionTypesVo.setStereotypes(rowElementTypeVo.getStereotypes());
        criterionTypesVo.setPrimitiveTypes(primitiveTypes);
        return criterionTypesVo;
    }

    @Transactional
    @NotNull
    public ModelResultVo sortValue(SortModelDTO dto) {
        LogUtil.printSerializeOnlineLogs("sortValue -> dto: ", dto);
        final String projectId = dto.getProjectId();
        ModelResultVo modelResultVo = new ModelResultVo();

        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            internalPropertyService.sortPropertyValue(dto);
            transactionService.commit(projectId);
            modelResultVo.setInstanceId(dto.getInstanceId());
            InstanceVoUtils.fillModelResultVo(modelResultVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }

        return modelResultVo;
    }

    @NotNull
    public Boolean checkTypeValidOwner(CheckTypeValidOwnerDTO dto) {
        LogUtil.printSerializeOnlineLogs("checkTypeValidOwner -> dto: ", dto);
        final String projectId = dto.getProjectId();
        final String type = dto.getType();
        final String parentId = dto.getTargetInstanceId();
        final MetaClassInstance parent = internalUmlService.fetchExistInstance(parentId, projectId);

        //针对uaf特殊的几个要特殊处理
        if (UAFDefinitionConstants.INVALID_OWNER.contains(type)) {
            return false;
        }

        // validNodeOwner
        // 1.校验语法
        if (!internalUmlService.canSetAsOwner(projectId, type, parent)) {
            return false;
        }
        if (businessJudgeService.isReadOnly(projectId, parent)) {
            return false;
        }

        if (internalUmlService.getGeneralIdsCascade(projectId, type)
                .contains(UMLDefinitionConstants.SysML_AbstractRequirement)) {
            return internalUmlService.checkInstanceType(projectId, parent, UMLDefinitionConstants.Package)
                    || internalUmlService.checkInstanceType(projectId, parent,
                    UMLDefinitionConstants.SysML_AbstractRequirement)
                    || internalUmlService.checkInstanceType(projectId, parent, UMLDefinitionConstants.Profile);
        }

        return true;
    }

    @NotNull
    public AllPropertyVo queryAllProperty(String projectId) {
        LogUtil.printOnlineLogs("queryAllProperty -> projectId: ", projectId);
        AllPropertyVo allPropertyVo = new AllPropertyVo();
        Map<String, List<MetaClassInstance>> propertiesMap = elementDefineService.queryAllMClasAndStereotypeProperties(projectId);
        List<MetaClassInstance> normalProperties = propertiesMap.get(CommonConstants.DOC_NORMAL)
                .stream().filter(it -> !Objects.equals(it.getId(), UMLDefinitionConstants.SysML_AbstractRequirement_id)).collect(Collectors.toList());
        List<MetaClassInstance> customizeProperties = propertiesMap.get(CommonConstants.DOC_CUSTOM);
        List<MetaClassInstance> otherProperties = propertiesMap.get(CommonConstants.DOC_OTHER);
        Map<String, ModelPropertyInfo> modelPropertyInfoMap = modelPropertyInfoService.createModelPropertyInfoMap(projectId,
                Stream.of(normalProperties, customizeProperties, otherProperties).flatMap(Collection::stream).collect(Collectors.toList()),
                Collections.singletonList(UMLDefinitionConstants.NamedElement_name));
        allPropertyVo.setNormalProperties(normalProperties.stream().map(it -> {
            PropertyConfig propertyConfig = new PropertyConfig();
            propertyConfig.setKey(it.getId());
            propertyConfig.setName(modelPropertyInfoMap.get(it.getId()).queryStringValue(UMLDefinitionConstants.NamedElement_name));
            return propertyConfig;
        }).collect(Collectors.toList()));
        allPropertyVo.setCustomizeProperties(customizeProperties.stream().map(it -> {
            PropertyConfig propertyConfig = new PropertyConfig();
            propertyConfig.setKey(it.getId());
            propertyConfig.setName(modelPropertyInfoMap.get(it.getId()).queryStringValue(UMLDefinitionConstants.NamedElement_name));
            return propertyConfig;
        }).collect(Collectors.toList()));
        allPropertyVo.setOtherProperties(otherProperties.stream().map(it -> {
            PropertyConfig propertyConfig = new PropertyConfig();
            propertyConfig.setKey(it.getId());
            propertyConfig.setName(modelPropertyInfoMap.get(it.getId()).queryStringValue(UMLDefinitionConstants.NamedElement_name));
            return propertyConfig;
        }).collect(Collectors.toList()));
        return allPropertyVo;

    }

    /**
     * 根据源和目标判断属性应该应用的构造型
     *
     * @param projectId
     * @param sourceInstanceId
     * @param targetInstanceId
     * @return
     */
    @NotNull
    public List<String> queryPropertyStereotype(String projectId, String sourceInstanceId, String targetInstanceId) {
        Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(Stream.of(sourceInstanceId, targetInstanceId).collect(Collectors.toList()), projectId);
        if (instanceMap.size() != 2) {
            return Collections.singletonList(UMLDefinitionConstants.Property);
        }
        List<String> list = new ArrayList<>();
        String appliedStereotype = modelConstraintService.getAppliedStereotypeForProperty(projectId, instanceMap.get(sourceInstanceId), instanceMap.get(targetInstanceId));
        if (StringUtils.isEmpty(appliedStereotype)) {
            list.add(UMLDefinitionConstants.Property);
        } else {
            list.add(appliedStereotype);
            list.add(UMLDefinitionConstants.Customization_PartProperty);
        }
        return list;
    }

    @NotNull
    public PropertyConfigTip queryTip(String propertyKey) {
        LogUtil.printOnlineLogs("propertyKey: ", propertyKey);
        if (modelManagerConfig.getPropertyConfigTips().containsKey(propertyKey)) {
            return modelManagerConfig.getPropertyConfigTips().get(propertyKey);
        } else {
            PropertyConfigTip tip = new PropertyConfigTip();
            tip.setKey(propertyKey);
            return tip;
        }
    }

    @NotNull
    public List<ItemInfo> queryItems(String projectId, String instanceId, String propertyKey) {
        LogUtil.printOnlineLogs("projectId: {}, instanceId: {}, propertyKey: {}", projectId, instanceId, propertyKey);
        if (StringUtils.equals(UMLDefinitionConstants.Property_defaultValue, propertyKey)) {
            MetaClassInstance instance = internalUmlService.fetchExistInstance(instanceId, projectId);
            ModelPropertyInfo model = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId, instance,
                    Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.TypedElement_type).collect(Collectors.toList()));
            return internalPropertyService.queryItemInfo(projectId, model);
        }

        if (modelManagerConfig.getPropertyConfigItems().containsKey(propertyKey)) {
            return modelManagerConfig.getPropertyConfigItems().get(propertyKey).getItems();
        }

        MetaClassInstance property = internalUmlService.fetchInstance(propertyKey, projectId);
        if (property != null) {
            ModelPropertyInfo model = modelPropertyInfoService.createSimpleModelPropertyInfo(projectId, property,
                    Stream.of(UMLDefinitionConstants.NamedElement_name, UMLDefinitionConstants.TypedElement_type).collect(Collectors.toList()));
            List<ItemInfo> itemInfoList = internalPropertyService.queryItemInfo(projectId, model);
            itemInfoList = itemInfoList.stream().filter(e -> !e.getLabel().isEmpty()).collect(Collectors.toList());
            return itemInfoList;
        }

        return Collections.emptyList();
    }

    @NotNull
    public List<AddModelItem> queryAddItems(String propertyKey) {
        LogUtil.printOnlineLogs("propertyKey: ", propertyKey);
        if (modelManagerConfig.getPropertyConfigItems().containsKey(propertyKey)) {
            return modelManagerConfig.getPropertyConfigItems().get(propertyKey).getAddModelItems();
        }

        return Collections.emptyList();
    }

    @NotNull
    public List<CheckValidPropertyValueVo> checkTypeValidOwnerList(CheckTypeValidOwnerDTO dto) {
        LogUtil.printSerializeOnlineLogs("checkTypeValidOwnerList -> dto: ", dto);
        String type = dto.getType();
        String projectId = dto.getProjectId();
        String targetInstanceId = dto.getTargetInstanceId();
        if (StringUtils.isEmpty(type)) {
            return Collections.emptyList();
        }
        if (StringUtils.isEmpty(targetInstanceId)) {
            // targetInstanceId为空，则说明是根节点
            Project project = this.projectManager.getProject(projectId);
            String rootId = Objects.isNull(project) ? null : project.getRootModel();
            return StringUtils.isEmpty(rootId) ? new ArrayList<>() :
                    propertyManager.checkValidPropertyValue(projectId, type, rootId);
        }
        return propertyManager.checkTypeValidOwnerList(projectId, type, targetInstanceId);
    }

    /**
     * description:保存属性映射配置
     */
    @NotNull
    public SavePropertyMappingVo savePropertyMapping(@NotNull SavePropertyMappingDTO savePropertyMappingDTO) {

        final String projectId = savePropertyMappingDTO.getProjectId();
        SavePropertyMappingVo savePropertyMappingVo = new SavePropertyMappingVo();
        LocalTransaction transaction = transactionService.createTransaction(projectId, ADD_MODEL);
        try {
            List<PropertyMapping> propertyMappings = savePropertyMappingDTO.getPropertyMappings();
            //获取当前语言环境
            Locale locale = LocaleContextHolder.getLocale();
            String language = locale.toLanguageTag();
            // 1.预校验:过滤掉不符合条件的映射规则，并记录原因(1.目标模型只读 2.属性类型不匹配 3.多重性不匹配)
            Pair<List<PropertyMapping>, List<SyncFailTip>> readOnlyPair = filterReadOnlyRule(projectId, propertyMappings, true, language);
            Pair<List<PropertyMapping>, List<SyncFailTip>> misMatchTypePair = filterMisMatchTypeRule(projectId, readOnlyPair.getLeft(), language);
            Pair<List<PropertyMapping>, List<SyncFailTip>> misMatchMultiplicityPair = filterMisMatchMultiplicityRule(
                    projectId, misMatchTypePair.getLeft(), language);
            List<PropertyMapping> legitMappings = misMatchMultiplicityPair.getLeft();
            // 2.新增的规则需要先生成对应的属性映射规则
            List<AddModelDTO> addModelDTOS = new ArrayList<>();
            legitMappings.forEach(propertyMapping -> {
                final String instanceId = propertyMapping.getInstanceId();
                if (instanceId == null) {
                    final String newInstanceId = SnowflakeIdWorkerUtil.getId();
                    // 设置新增规则id
                    propertyMapping.setInstanceId(newInstanceId);
                    // 生成新增规则Command
                    AddModelDTO addModelDTO = new AddModelDTO();
                    addModelDTO.setProjectId(projectId);
                    addModelDTO.setInstanceId(newInstanceId);
                    addModelDTO.setType(CommandAddType.MODEL.getCode());
                    addModelDTO.setMetaclass(UMLDefinitionConstants.Class);
                    addModelDTO.setApplyStereotypes(Collections.singletonList(UMLDefinitionConstants.Customization_PropertySyncRule));
                    addModelDTO.setParentId(propertyMapping.getParentId());
                    addModelDTOS.add(addModelDTO);
                }
            });
            if (CollectionUtils.isNotEmpty(addModelDTOS)) {
                umlService.addModel(addModelDTOS);
            }

            // 3.更新映射配置属性
            List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
            List<String> instanceIds = propertyMappings.stream().flatMap(it -> Stream.of(it.getInstanceId(), it.getTargetInstanceId()))
                    .filter(Objects::nonNull).collect(Collectors.toList());
            Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(instanceIds, projectId);
            MofResultContainer nameContainer = internalUmlService.getMofResultContainer(
                    projectId, new ArrayList<>(instanceMap.values()), UMLDefinitionConstants.NamedElement_name);
            legitMappings.forEach(propertyMapping -> {
                final String instanceId = propertyMapping.getInstanceId();
                final String sourceInstanceId = propertyMapping.getSourceInstanceId();
                final String sourcePropertyKey = propertyMapping.getSourcePropertyKey();
                final String targetInstanceId = propertyMapping.getTargetInstanceId();
                final String targetPropertyKey = propertyMapping.getTargetPropertyKey();
                final Boolean isReplace = propertyMapping.getIsReplace();
                // id改造后更新不需要传模型，所以这里不批量查询模型
                updateModelDTOS.add(new UpdateModelDTO(projectId, instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_sourceElement,
                        internalUmlService.fetchInstance(sourceInstanceId, projectId)));
                updateModelDTOS.add(new UpdateModelDTO(projectId, instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_targetElement,
                        internalUmlService.fetchInstance(targetInstanceId, projectId)));
                updateModelDTOS.add(new UpdateModelDTO(projectId, instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_sourceProperty,
                        sourcePropertyKey));
                updateModelDTOS.add(new UpdateModelDTO(projectId, instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_targetProperty,
                        targetPropertyKey));
                updateModelDTOS.add(new UpdateModelDTO(projectId, instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_isReplace,
                        isReplace));
                // 更新同步规则名称:目标模型名称+目标模型属性名称+同步
                String targetInstanceName = nameContainer.queryStringProperty(targetInstanceId, UMLDefinitionConstants.NamedElement_name);
                if (StringUtils.isEmpty(targetInstanceName)) {
                    targetInstanceName = "  ";
                }
                PropertyConfig targetPropertyConfig = managerConfig.getPropertyConfigs().get(propertyMapping.getTargetPropertyKey());
                String targetPropertyName = targetPropertyConfig == null ? targetPropertyKey : targetPropertyConfig.getName();
                String originName = targetInstanceName + targetPropertyName + "同步";
                MetaClassInstance instance = instanceMap.get(instanceId);
                MetaClassInstance parentInstance = internalUmlService.fetchInstance(instance.getOwnerId(), projectId);
                String finalName = elementNameService.fetchDefaultName(projectId, originName, parentInstance, instance);
                // 批量更新会导致重名，需要拿map先存名称更新指令
                umlService.updateModel(projectId, instanceId, UMLDefinitionConstants.NamedElement_name, finalName);
            });
            umlService.updateModelByBatch(updateModelDTOS);

            // 4.将所有属性映射配置模型返回给前端
            savePropertyMappingVo.setSuccessInstanceIds(legitMappings.stream().map(PropertyMapping::getInstanceId).collect(Collectors.toList()));
            savePropertyMappingVo.setPropertyMappingIdMap(legitMappings.stream().collect(Collectors.toMap(
                    PropertyMapping::getUuid, PropertyMapping::getInstanceId, (k, v) -> k)));
            List<SyncFailTip> syncFailTips = Stream.of(readOnlyPair.getRight(), misMatchTypePair.getRight(),
                    misMatchMultiplicityPair.getRight()).flatMap(Collection::stream).collect(Collectors.toList());
            savePropertyMappingVo.setErrorTips(syncFailTips);
            savePropertyMappingVo.setSuccessNum(legitMappings.size());
            savePropertyMappingVo.setFailNum(propertyMappings.size() - legitMappings.size());
            transactionService.commit(projectId);
            InstanceVoUtils.fillModelResultVo(savePropertyMappingVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }
        return savePropertyMappingVo;
    }


    @NotNull
    public ModelErrorInfoVo<List<SyncFailTip>> syncPropertyMapping(@NotNull SyncPropertyMappingDTO syncPropertyMappingDTO) {
        final String projectId = syncPropertyMappingDTO.getProjectId();
        ModelErrorInfoVo<List<SyncFailTip>> modelErrorInfoVo = new ModelErrorInfoVo<>();
        // 1.查询同步映射规则模型属性值
        final List<String> instanceIds = syncPropertyMappingDTO.getInstanceIds();
        if (CollectionUtils.isEmpty(instanceIds)) {
            log.info("需同步的映射配置为空");
            return modelErrorInfoVo;
        }
        List<MetaClassInstance> mappingInstances =
                internalUmlService.fetchInstanceByIds(instanceIds, projectId).stream()
                        .filter(it -> internalUmlService.checkInstanceType(projectId, it,
                                UMLDefinitionConstants.Customization_PropertySyncRule)).collect(Collectors.toList());
        MofResultContainer mappingContainer = internalUmlService.getMofResultContainer(projectId, mappingInstances,
                Stream.of(UMLDefinitionConstants.Customization_PropertySyncRule_sourceElement,
                        UMLDefinitionConstants.Customization_PropertySyncRule_targetElement,
                        UMLDefinitionConstants.Customization_PropertySyncRule_sourceProperty,
                        UMLDefinitionConstants.Customization_PropertySyncRule_targetProperty,
                        UMLDefinitionConstants.Customization_PropertySyncRule_isReplace).collect(Collectors.toList()));
        List<PropertyMapping> propertyMappings =
                mappingInstances.stream().filter(it -> internalUmlService.checkInstanceType(projectId, it,
                        UMLDefinitionConstants.Customization_PropertySyncRule)).map(it -> {
                    final String instanceId = it.getId();
                    MetaClassInstance sourceElement = mappingContainer.queryInstanceProperty(
                            instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_sourceElement);
                    MetaClassInstance targetElement = mappingContainer.queryInstanceProperty(
                            instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_targetElement);
                    PropertyMapping propertyMapping = new PropertyMapping();
                    propertyMapping.setInstanceId(instanceId);
                    propertyMapping.setSourceInstanceId(Optional.ofNullable(sourceElement).map(BasicRElement::getId).orElse(null));
                    propertyMapping.setTargetInstanceId((Optional.ofNullable(targetElement).map(BasicRElement::getId).orElse(null)));
                    propertyMapping.setSourcePropertyKey(mappingContainer.queryStringProperty(
                            instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_sourceProperty));
                    propertyMapping.setTargetPropertyKey(mappingContainer.queryStringProperty(
                            instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_targetProperty));
                    propertyMapping.setIsReplace(mappingContainer.queryBooleanProperty(
                            instanceId, UMLDefinitionConstants.Customization_PropertySyncRule_isReplace));
                    return propertyMapping;
                }).collect(Collectors.toList());
        //获取当前语言环境
        Locale locale = LocaleContextHolder.getLocale();
        String language = locale.toLanguageTag();
        // 2.校验同步规则是否符合条件
        // 2.1 过滤是否替换的规则
        Pair<List<PropertyMapping>, List<SyncFailTip>> misMatchReplacePair = filterMisMatchReplaceRule(projectId, propertyMappings, language);
        // 2.2 过滤目标模型只读的规则
        Pair<List<PropertyMapping>, List<SyncFailTip>> readOnlyPair = filterReadOnlyRule(projectId, misMatchReplacePair.getLeft(), false, language);
        // 2.3 过滤类型不一致的规则
        Pair<List<PropertyMapping>, List<SyncFailTip>> misMatchTypePair = filterMisMatchTypeRule(projectId, readOnlyPair.getLeft(), language);
        // 2.4 过滤多重性不一致规则
        Pair<List<PropertyMapping>, List<SyncFailTip>> misMatchMultiplicityPair = filterMisMatchMultiplicityRule(
                projectId, misMatchTypePair.getLeft(), language);
        List<SyncFailTip> syncFailTips = Stream.of(misMatchReplacePair.getRight(), readOnlyPair.getRight(), misMatchTypePair.getRight(),
                misMatchMultiplicityPair.getRight()).flatMap(Collection::stream).collect(Collectors.toList());
        List<PropertyMapping> legitMappings = misMatchMultiplicityPair.getLeft();
        LocalTransaction transaction = transactionService.createTransaction(projectId, UPDATE_MODEL);
        try {
            // 3.将过滤后的规则进行同步
            final List<String> allIds = propertyMappings.stream().map(PropertyMapping::getSourceInstanceId).collect(Collectors.toList());
            Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(allIds, projectId);
            QueryPropertyForm queryPropertyForm = new QueryPropertyForm();
            propertyMappings.forEach(propertyMapping -> queryPropertyForm.add(
                    instanceMap.get(propertyMapping.getSourceInstanceId()), propertyMapping.getSourcePropertyKey()));
            MofResultContainer modelContainer = internalUmlService.queryProperty(projectId, queryPropertyForm);

            List<UpdateModelDTO> updateModelDTOS = createUpdateModelDTOS(legitMappings, projectId, modelContainer);

            umlService.updateModelByBatch(updateModelDTOS);
            transactionService.commit(projectId);
            modelErrorInfoVo.setErrorTips(syncFailTips);
            modelErrorInfoVo.setSuccessNum(instanceIds.size() - syncFailTips.size());
            modelErrorInfoVo.setFailNum(syncFailTips.size());
            InstanceVoUtils.fillModelResultVo(modelErrorInfoVo, transaction);
        } catch (TransactionNotExistingException | LocalTransactionNotStartException e) {
            throw AbortExecutionException.build(ErrorCode.TRANSACTION_ERROR, e);
        } catch (Exception e) {
            transactionService.rollBack(projectId, transaction);
            throw AbortExecutionException.build(ErrorCode.SERVICE_ERROR, e);
        }
        return modelErrorInfoVo;
    }

    private List<UpdateModelDTO> createUpdateModelDTOS(List<PropertyMapping> legitMappings, String projectId, MofResultContainer modelContainer) {
        List<UpdateModelDTO> updateModelDTOS = new ArrayList<>();
        legitMappings.forEach(legitMapping -> {
            final String sourceProperty = legitMapping.getSourcePropertyKey();
            final String targetProperty = legitMapping.getTargetPropertyKey();
            final String targetInstanceId = legitMapping.getTargetInstanceId();
            Boolean sourceIsMultiplicity = elementPropertyService.isMultiplicity(projectId, sourceProperty);
            Object sourceValue = BooleanUtils.isTrue(sourceIsMultiplicity) ?
                    modelContainer.queryListObjectProperty(legitMapping.getSourceInstanceId(), sourceProperty) :
                    modelContainer.queryObjectProperty(legitMapping.getSourceInstanceId(), sourceProperty);
            // 派生属性多重性为1时，查出来的value为List
            sourceValue = Optional.of(sourceValue).filter(e -> BooleanUtils.isFalse(sourceIsMultiplicity) && e instanceof Collection).
                    map(List.class::cast).filter(CollectionUtils::isNotEmpty).map(e -> e.get(0)).orElse(sourceValue);

            // 默认值特殊处理：1.默认值->普通属性 2.默认值->默认值 3.普通属性->默认值
            if (UMLDefinitionConstants.Property_defaultValue.equals(sourceProperty) ||
                    UMLDefinitionConstants.Property_defaultValue.equals(targetProperty)) {
                updateDefaultValue(projectId, legitMapping, sourceValue);
            } else if (SyncRuleProperty.SPECIAL_HANDLE_PROPERTY.contains(targetProperty)) {
                ModifyPropertyDTO modifyPropertyDTO = new ModifyPropertyDTO();
                modifyPropertyDTO.setProjectId(projectId);
                modifyPropertyDTO.setInstanceId(targetInstanceId);
                modifyPropertyDTO.setKey(targetProperty);
                List<Object> originValueList = sourceValue instanceof Collection ?
                        (List<Object>) sourceValue : Collections.singletonList(sourceValue);
                List<Object> modifyValue = originValueList.stream().map(it -> it instanceof MetaClassInstance ?
                        ((MetaClassInstance) it).getId() : it).collect(Collectors.toList());
                modifyPropertyDTO.setValue(modifyValue);
                propertyManager.updatePropertyValue(modifyPropertyDTO);
            } else if (UMLDefinitionConstants.Property_datatype.equals(targetProperty) && sourceValue == null) {
                log.warn("如果更新的目标属性为Property-datatype且更新值为null，更新后会导致Owner丢失，故跳过处理");
            } else {
                updateModelDTOS.add(new UpdateModelDTO(projectId, targetInstanceId, targetProperty, sourceValue));
            }
        });
        return updateModelDTOS;
    }

    private void updateDefaultValue(@NotNull String projectId,
                                    @NotNull PropertyMapping legitMapping,
                                    @Nullable Object sourceValue) {
        String sourceProperty = legitMapping.getSourcePropertyKey();
        String targetProperty = legitMapping.getTargetPropertyKey();
        String targetInstanceId = legitMapping.getTargetInstanceId();

        // 1.查询真实的属性值(默认值下的slotValue)
        Object sourceRealValue;
        if (UMLDefinitionConstants.Property_defaultValue.equals(sourceProperty) && sourceValue != null) {
            ValueSpecificationInfo valueSpecificationInfo = internalSpecificationService.queryValueFromValueSpecification(projectId, (MetaClassInstance) sourceValue);
            String metaclass = valueSpecificationInfo.getMetaclass();
            if (StringUtils.equals(metaclass, UMLDefinitionConstants.InstanceValue)) {
                sourceRealValue = valueSpecificationInfo.getElementId();
            } else {
                sourceRealValue = valueSpecificationInfo.getValue();
            }
        } else {
            sourceRealValue = sourceValue;
        }
        // 如果批量更新的话 多条同步规则更新同一模型默认值可能创建多个ValueSpecification 此时批量更新会报Owner丢失
        if (UMLDefinitionConstants.Property_defaultValue.equals(targetProperty)) {
            String syncTypeId = getSyncTypeByPropertyKey(projectId, targetInstanceId, targetProperty);
            String metaClass = internalSpecificationService.getValuespecificationType(
                    projectId, internalUmlService.fetchInstance(syncTypeId, projectId));
            MetaClassInstance targetInstance = internalUmlService.fetchExistInstance(targetInstanceId, projectId);
            MetaClassInstance existValueSpecification = internalUmlService.queryInstanceProperty(
                    projectId, targetInstance, UMLDefinitionConstants.Property_defaultValue);
            MetaClassInstance finalValueSpecification = internalSpecificationService.createValueSpecificationByType(
                    projectId, metaClass, sourceRealValue, null,
                    existValueSpecification != null ? existValueSpecification.getId() : null);

            umlService.updateModel(projectId, targetInstanceId, targetProperty, finalValueSpecification);
        } else {
            umlService.updateModel(projectId, targetInstanceId, targetProperty, sourceRealValue);
        }

    }


    /**
     * @param projectId        项目id
     * @param propertyMappings 属性映射规则信息
     * @param isValidRule      true:校验rule本身是否只读；false:校验rule的target元素是否只读
     * @description:过滤目标模型只读的规则，并生成相应的错误tips
     * @author lx
     * @date 2024/8/9
     */
    @NotNull
    private Pair<List<PropertyMapping>, List<SyncFailTip>> filterReadOnlyRule(@NotNull String projectId,
                                                                              @NotNull List<PropertyMapping> propertyMappings,
                                                                              boolean isValidRule,
                                                                              @NotNull String language) {
        List<PropertyMapping> filteredMappings = new ArrayList<>();
        List<PropertyMapping> failedMappings = new ArrayList<>();

        final List<String> allIds = propertyMappings.stream().flatMap(it ->
                Stream.of(it.getTargetInstanceId(), it.getInstanceId())).collect(Collectors.toList());
        Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(allIds, projectId);
        Map<String, Boolean> readOnlyMap = businessJudgeService.isReadOnly(projectId, new ArrayList<>(instanceMap.values()));
        propertyMappings.forEach(propertyMapping -> {
            final String validInstanceId = isValidRule ? propertyMapping.getInstanceId() : propertyMapping.getTargetInstanceId();
            if (BooleanUtils.isTrue(readOnlyMap.get(validInstanceId))) {
                failedMappings.add(propertyMapping);
            } else {
                filteredMappings.add(propertyMapping);
            }
        });
        String failReason = isValidRule ? "同步规则无编辑权限" : "目标元素无编辑权限";
        List<SyncFailTip> syncFailTips = buildFailTips(projectId, failedMappings, failReason);
        return Pair.of(filteredMappings, syncFailTips);
    }

    /**
     * description:过滤属性类型不匹配的规则，并生成相应的错误tips
     */
    @NotNull
    private Pair<List<PropertyMapping>, List<SyncFailTip>> filterMisMatchTypeRule(@NotNull String projectId,
                                                                                  @NotNull List<PropertyMapping> propertyMappings,
                                                                                  @NotNull String language) {
        List<PropertyMapping> filteredMappings = new ArrayList<>();
        List<PropertyMapping> failedMappings = new ArrayList<>();
        propertyMappings.forEach(propertyMapping -> {
            final String sourcePropertyKey = propertyMapping.getSourcePropertyKey();
            final String targetPropertyKey = propertyMapping.getTargetPropertyKey();
            // 模型类型校验处理
            String sourcePropertyType = getSyncTypeByPropertyKey(projectId, propertyMapping.getSourceInstanceId(), sourcePropertyKey);
            String targetPropertyType = getSyncTypeByPropertyKey(projectId, propertyMapping.getTargetInstanceId(), targetPropertyKey);
            if (sourcePropertyType == null || targetPropertyType == null) {
                log.warn("同步规则源属性值类型或目标属性值类型为空, 源属性值类型:{},目标属性值类型:{}", sourcePropertyKey, targetPropertyKey);
                failedMappings.add(propertyMapping);
                return;
            }

            // 源模型类型与默认值一致性校验，防止后续同步时出现属性类型不匹配问题
            if (UMLDefinitionConstants.Property_defaultValue.equals(sourcePropertyKey)) {
                MetaClassInstance sourceInstance = internalUmlService.fetchInstance(
                        propertyMapping.getSourceInstanceId(), projectId);
                MetaClassInstance defaultValue = internalUmlService.queryInstanceProperty(projectId, sourceInstance, UMLDefinitionConstants.Property_defaultValue);
                if (defaultValue != null) {
                    ValueSpecificationInfo valueSpecificationInfo =
                            internalSpecificationService.queryValueFromValueSpecification(projectId, defaultValue);
                    String metaClass = internalSpecificationService.getValuespecificationType(
                            projectId, internalUmlService.fetchInstance(sourcePropertyType, projectId));
                    if (!StringUtils.equals(valueSpecificationInfo.getMetaclass(), metaClass)) {
                        log.warn("源属性的类型与默认值ValueSpecification类型不一致");
                        failedMappings.add(propertyMapping);
                        return;
                    }
                }
            }

            Set<String> sourceGivenTypes = new HashSet<>();
            if (!internalUmlService.checkMetaModelType(
                    projectId, internalUmlService.fetchInstance(sourcePropertyType, projectId), UMLDefinitionConstants.Classifier)) {
                sourceGivenTypes.add(sourcePropertyType);
            } else {
                List<String> baseClassList = internalUmlService.getSelfBasePropertyList(
                        projectId, internalUmlService.fetchExistInstance(sourcePropertyType, projectId));
                sourceGivenTypes.addAll(Stream.concat(baseClassList.stream(), Stream.of(sourcePropertyType))
                        .flatMap(it -> internalUmlService.getGeneralIdsCascade(projectId, it).stream()).collect(Collectors.toSet()));
            }

            if (sourceGivenTypes.contains(targetPropertyType)) {
                filteredMappings.add(propertyMapping);
            } else {
                failedMappings.add(propertyMapping);
            }
        });

        //失败原因
        String failReason;
        if (TipConstant.LanguageType.English.equals(language)) {
            failReason = TipConstant.PropertySynTip.TypeInconsistent_English;
        } else {
            failReason = TipConstant.PropertySynTip.TypeInconsistent_en_US;
        }

        List<SyncFailTip> syncFailTips = buildFailTips(projectId, failedMappings, failReason);
        return Pair.of(filteredMappings, syncFailTips);
    }

    @Nullable
    private String getSyncTypeByPropertyKey(@NotNull String projectId,
                                            @NotNull String instanceId,
                                            @NotNull String propertyKey) {
        // 1. 遵循语法校验规则
        String typeId = elementPropertyService.queryPropertyTypeId(projectId, propertyKey);
        // typeId == null：queryPropertyTypeId查询派生属性类型为null(queryPropertyTypeId和queryPropertyDataType需要mof fix)
        // Property_defaultValue：业务特殊处理，否则typeId为InstanceSpecification
        String targetInstanceId = UMLDefinitionConstants.Property_defaultValue.equals(propertyKey) ? instanceId : propertyKey;
        if (typeId == null || UMLDefinitionConstants.Property_defaultValue.equals(propertyKey)) {
            MetaClassInstance type = internalUmlService.queryInstanceProperty(
                    projectId, internalUmlService.fetchInstance(targetInstanceId, projectId), UMLDefinitionConstants.TypedElement_type);
            return type == null ? null : type.getId();
        }
        // 2.特殊处理属性需遵循业务的模型校验规则
        if (SyncRuleProperty.SPECIAL_HANDLE_PROPERTY.contains(propertyKey)) {
            PropertyConfig propertyConfig = modelManagerConfig.getPropertyConfigs().get(propertyKey);
            if (propertyConfig != null && propertyConfig.getMoreBtnCondition() != null) {
                typeId = propertyConfig.getMoreBtnCondition();
            }
        }
        return typeId;
    }

    /**
     * description:过滤多重性不匹配的规则，并生成相应的错误tips
     */
    @NotNull
    private Pair<List<PropertyMapping>, List<SyncFailTip>> filterMisMatchMultiplicityRule(@NotNull String projectId,
                                                                                          @NotNull List<PropertyMapping> propertyMappings,
                                                                                          @NotNull String language) {
        List<PropertyMapping> filteredMappings = new ArrayList<>();
        List<PropertyMapping> failedMappings = new ArrayList<>();

        List<String> allPropertyKeys = propertyMappings.stream().flatMap(it ->
                Stream.of(it.getSourcePropertyKey(), it.getTargetPropertyKey())).collect(Collectors.toList());
        Map<String, Integer> propertyLowerMap = elementPropertyService.queryPropertyLower(projectId, allPropertyKeys);
        Map<String, String> propertyUpperMap = elementPropertyService.queryPropertyUpper(projectId, allPropertyKeys);
        propertyMappings.forEach(propertyMapping -> {
            final String sourcePropertyKey = propertyMapping.getSourcePropertyKey();
            final String targetPropertyKey = propertyMapping.getTargetPropertyKey();
            Integer sourcePropertyLower = propertyLowerMap.get(sourcePropertyKey);
            Integer targetPropertyLower = propertyLowerMap.get(targetPropertyKey);
            String sourcePropertyUpper = propertyUpperMap.get(sourcePropertyKey);
            String targetPropertyUpper = propertyUpperMap.get(targetPropertyKey);
            if (sourcePropertyLower == null || targetPropertyLower == null || sourcePropertyUpper == null || targetPropertyUpper == null) {
                log.error("源属性、目标属性的上下限查询失败:源属性为{},目标属性为{}", sourcePropertyKey, targetPropertyKey);
                throw AbortExecutionException.build(ErrorCode.PROPERTY_QUERY_ERROR);
            }
            // 如果源属性下限小于目标属性下限 或 源属性上限大于目标属性上限，规则不符合同步条件
            int sourcePropertyUpperValue = sourcePropertyUpper.equals("-1") ?
                    Integer.MAX_VALUE : Integer.parseInt(sourcePropertyUpper);
            int targetPropertyUpperValue = targetPropertyUpper.equals("-1") ?
                    Integer.MAX_VALUE : Integer.parseInt(targetPropertyUpper);
            if (sourcePropertyLower < targetPropertyLower || targetPropertyUpperValue < sourcePropertyUpperValue) {
                failedMappings.add(propertyMapping);
            } else {
                filteredMappings.add(propertyMapping);
            }
        });

        //失败原因
        String failReason = null;
        if (TipConstant.LanguageType.English.equals(language)) {
            failReason = TipConstant.PropertySynTip.Multiplicity_Inconsistent_English;
        } else {
            failReason = TipConstant.PropertySynTip.Multiplicity_Inconsistent_en_US;
        }

        List<SyncFailTip> syncFailTips = buildFailTips(projectId, failedMappings, failReason);
        return Pair.of(filteredMappings, syncFailTips);
    }

    @NotNull
    private Pair<List<PropertyMapping>, List<SyncFailTip>> filterMisMatchReplaceRule(@NotNull String projectId,
                                                                                     @NotNull List<PropertyMapping> propertyMappings,
                                                                                     @NotNull String language) {
        List<PropertyMapping> filteredMappings = new ArrayList<>();
        List<PropertyMapping> failedMappings = new ArrayList<>();

        final List<String> allIds = propertyMappings.stream().map(PropertyMapping::getTargetInstanceId).collect(Collectors.toList());
        Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(allIds, projectId);
        QueryPropertyForm queryPropertyForm = new QueryPropertyForm();
        propertyMappings.forEach(propertyMapping -> {
            MetaClassInstance targetInstance = instanceMap.get(propertyMapping.getTargetInstanceId());
            if (targetInstance != null) {
                queryPropertyForm.add(
                        instanceMap.get(propertyMapping.getTargetInstanceId()), propertyMapping.getTargetPropertyKey());
            }
        });
        MofResultContainer mofResultContainer = internalUmlService.queryProperty(projectId, queryPropertyForm);
        propertyMappings.forEach(propertyMapping -> {
            final String targetInstanceId = propertyMapping.getTargetInstanceId();
            final String targetPropertyKey = propertyMapping.getTargetPropertyKey();
            Boolean targetIsMultiplicity = internalUmlService.isMultiplicity(projectId, targetPropertyKey);
            List<Object> targetValueList = new ArrayList<>();
            if (BooleanUtils.isTrue(targetIsMultiplicity)) {
                targetValueList.addAll(mofResultContainer.queryListObjectProperty(targetInstanceId, targetPropertyKey));
            } else {
                Object targetValue = mofResultContainer.queryObjectProperty(targetInstanceId, targetPropertyKey);
                if (targetValue != null) {
                    targetValueList.add(targetValue);
                }
            }
            if (BooleanUtils.isFalse(propertyMapping.getIsReplace()) && CollectionUtils.isNotEmpty(targetValueList)) {
                failedMappings.add(propertyMapping);
            } else {
                filteredMappings.add(propertyMapping);
            }
        });

        //失败原因
        String failReason = null;
        if (TipConstant.LanguageType.English.equals(language)) {
            failReason = TipConstant.PropertySynTip.ValueExistNotExecuted_English;
        } else {
            failReason = TipConstant.PropertySynTip.ValueExistNotExecuted_en_US;
        }

        List<SyncFailTip> syncFailTips = buildFailTips(projectId, failedMappings, failReason);
        return Pair.of(filteredMappings, syncFailTips);
    }

    @NotNull
    private List<SyncFailTip> buildFailTips(@NotNull String projectId,
                                            @NotNull List<PropertyMapping> failPropertyMappings,
                                            @NotNull String failReason) {
        if (CollectionUtils.isEmpty(failPropertyMappings)) {
            return Collections.emptyList();
        }
        final List<String> allIds = failPropertyMappings.stream().flatMap(it ->
                Stream.of(it.getSourceInstanceId(), it.getTargetInstanceId())).collect(Collectors.toList());
        Map<String, MetaClassInstance> instanceMap = internalUmlService.fetchInstances(allIds, projectId);
        MofResultContainer mofResultContainer = internalUmlService.getMofResultContainer(
                projectId, new ArrayList<>(instanceMap.values()), UMLDefinitionConstants.NamedElement_name);
        Map<String, PropertyConfig> propertyConfigMap = modelManagerConfig.getPropertyConfigs();
        return failPropertyMappings.stream().map(it -> {
            SyncFailTip syncFailTip = new SyncFailTip();
            syncFailTip.setSourceName(mofResultContainer.queryStringProperty(it.getSourceInstanceId(), UMLDefinitionConstants.NamedElement_name));
            syncFailTip.setTargetName(mofResultContainer.queryStringProperty(it.getTargetInstanceId(), UMLDefinitionConstants.NamedElement_name));
            final PropertyConfig sourcePropertyConfig = propertyConfigMap.get(it.getSourcePropertyKey());
            syncFailTip.setSourcePropertyName(sourcePropertyConfig != null ? sourcePropertyConfig.getName() : null);
            syncFailTip.setSourcePropertyKey(sourcePropertyConfig != null ? sourcePropertyConfig.getKey() : null);
            final PropertyConfig targetPropertyConfig = propertyConfigMap.get(it.getTargetPropertyKey());
            syncFailTip.setTargetPropertyName(targetPropertyConfig != null ? targetPropertyConfig.getName() : null);
            syncFailTip.setTargetPropertyKey(targetPropertyConfig != null ? targetPropertyConfig.getKey() : null);
            syncFailTip.setFailedReason(failReason);
            return syncFailTip;
        }).collect(Collectors.toList());
    }


    public List<String> batchQueryElementDisplay(BatchQueryElementDisplayDTO dto) {
        List<MetaClassInstance> instances = internalUmlService.fetchInstanceByIds(dto.getInstanceIds(), dto.getProjectId());
        if (CollUtil.isEmpty(instances)) {
            return Collections.emptyList();
        }
        Map<String, Set<String>> givenTypes = internalUmlService.getGivenTypes(dto.getProjectId(), instances);
        Collection<Set<String>> values = givenTypes.values();
        List<String> menu = getMenu(CollUtil.get(values, 0), true);

        for (int i = 1; i < values.size(); i++) {
            menu = Lists.newArrayList(CollUtil.intersectionDistinct(menu, getMenu(CollUtil.get(values, i), true)));
        }
        return menu;
    }

}
